package net.googlecode.demenkov.services.impl;

import net.googlecode.demenkov.dao.FacultyDAO;
import net.googlecode.demenkov.dao.GroupDAO;
import net.googlecode.demenkov.dao.PersonDAO;
import net.googlecode.demenkov.dao.UniversityDAO;
import net.googlecode.demenkov.domains.Faculty;
import net.googlecode.demenkov.domains.Group;
import net.googlecode.demenkov.domains.Person;
import net.googlecode.demenkov.domains.University;
import net.googlecode.demenkov.services.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * Service class provided actions with person
 *
 * @author Demenkov Yura
 */
@Service
public class PersonServiceImpl implements PersonService {
    @Autowired
    private PersonDAO personDAO;
    @Autowired
    private GroupDAO groupDAO;
    @Autowired
    private FacultyDAO facultyDAO;
    @Autowired
    private UniversityDAO universityDAO;


    @Transactional(readOnly = true)
    public void createVote(Person fromPerson, Person toPerson) {
        personDAO.createVote(fromPerson, toPerson);
    }

    @Transactional(readOnly = true)
    public void deleteVote(Person fromPerson, Person toPerson) {
        personDAO.deleteVote(fromPerson, toPerson);
    }

    /**
     * Builds a person: finds group by groupname, facultyname and universityname from person's information or creates it
     * and sets it to person's group, also if person's avatar is empty, sets it as default avatar
     *
     * @param person to build
     * @return built person
     */
    @Transactional
    private Person buildPerson(Person person) {
        Group builtGroup = findGroupByGroupNameAndFacultyNameAndUniversityName(person.getGroup().getGroupName(), person.getGroup().getFaculty().getFacultyName(), person.getGroup().getFaculty().getUniversity().getUniversityName());
        if (builtGroup == null) {
            createGroup(person.getGroup().getGroupName(), person.getGroup().getFaculty().getFacultyName(), person.getGroup().getFaculty().getUniversity().getUniversityName());
            builtGroup = findGroupByGroupNameAndFacultyNameAndUniversityName(person.getGroup().getGroupName(), person.getGroup().getFaculty().getFacultyName(), person.getGroup().getFaculty().getUniversity().getUniversityName());
        }
        person.setGroup(builtGroup);
        if (person.getAvatar().isEmpty()) {
            person.setAvatar("avatar");
        }
        return person;
    }

    @Transactional
    public void createPerson(Person person) {
        personDAO.create(buildPerson(person));
    }

    @Transactional()
    public void updatePerson(Person person) {
        personDAO.update(buildPerson(person));
    }

    @Transactional(readOnly = true)
    public Person getPerson(int id) {
        return personDAO.get(id);
    }

    @Transactional(readOnly = true)
    public Person findPersonByEmail(String email) {
        return personDAO.findPersonByEmail(email);
    }

    @Transactional(readOnly = true)
    public Group findGroupByGroupNameAndFacultyNameAndUniversityName(String groupName, String factultyName, String universityName) {
        return groupDAO.findGroupByGroupNameAndFacultyNameAndUniversityName(groupName, factultyName, universityName);
    }

    @Transactional(readOnly = true)
    public List<Group> findAllGroupsByFacultyNameAndUniversityName(String facultyName, String universityName) {
        return groupDAO.findAllGroupsByFacultyNameAndUniversityName(facultyName, universityName);
    }

    @Transactional
    public void createGroup(String groupName, String facultyName, String universityName) {
        Group group = new Group();
        group.setGroupName(groupName);
        group.setFaculty(facultyDAO.findFacultyByFacultyNameAndUniversity(facultyName,
                universityDAO.findUniversityByUniversityName(universityName)));
        groupDAO.create(group);
    }

    @Transactional(readOnly = true)
    public Group getGroup(int groupId) {
        return groupDAO.get(groupId);
    }

    @Transactional(readOnly = true)
    public Faculty getFaculty(int facultyId) {
        return facultyDAO.get(facultyId);
    }

    @Transactional(readOnly = true)
    public University getUniversity(int universityId) {
        return universityDAO.get(universityId);
    }

    @Transactional
    public List<Faculty> findAllFacultiesByUniversityName(String universityName) {
        return facultyDAO.findAllFacultiesByUniversityName(universityName);
    }

    @Transactional
    public List<University> getAllUniversities() {
        return universityDAO.getAllUniversities();
    }
}
